package middlewares

import (
	"context"
	"errors"
	"net/http"
	"strconv"
	"time"

	"github.com/gin-gonic/gin"
	global "github.com/smash-llj/Nexa-server/global"
	utils "github.com/smash-llj/Nexa-server/utils"
	"github.com/spf13/viper"
)

func JwtAuth() gin.HandlerFunc {
	return func(c *gin.Context) {
		claims, err := utils.GetToken(c)
		if err != nil {
			unauthorizedResponse(c, err.Error())
			return
		}
		// Token验证通过，将claims保存到上下文
		c.Set("claims", claims)
		// 检查Token是否小于缓冲时间 如果是重新颁发token
		if isTokenExpired(c, claims) {
			return
		}
		c.Next()
	}
}

// 检查Token是否过期
func isTokenExpired(c *gin.Context, claims *utils.TokenClaims) bool {
	prefix := viper.GetString("Redis.PreFix") + strconv.Itoa(int(claims.Id))
	expressAt, err := GetExpires(prefix)
	if err != nil {
		unauthorizedResponse(c, "token更新失败")
		return true
	}
	// 检查是否接近过期，刷新Token
	if expressAt.Seconds() < float64(viper.GetInt64("Token.bufferTime")) {
		token, _ := utils.GenerateToken(utils.TokenUser{
			Name: claims.Name,
			Id:   claims.Id,
		})
		c.Header("x-token", token)
	}
	return false
}

// 统一未授权响应
func unauthorizedResponse(c *gin.Context, message string) {
	c.JSON(http.StatusUnauthorized, gin.H{
		"data": message,
	})
	c.Abort()
}

func GetExpires(key string) (time.Duration, error) {
	ttl, err := global.Redis.TTL(context.Background(), key).Result()
	if err != nil {
		return 0, errors.New("token不存在")
	}
	return ttl, nil
}
